home *** CD-ROM | disk | FTP | other *** search
/ Deutsche Edition 1 / Deutsche Edition 1.iso / amok / amok_lha / amok59.lha / AmokEd_V1.02b / txt / EdMovement.mod < prev    next >
Text File  |  1993-08-15  |  28KB  |  983 lines

  1. (*************************************************************************
  2.  
  3. :Program.    EdMovement.mod
  4. :Contents.   Cursor-Movement for AmokEd
  5. :Author.     Hartmut Goebel
  6. :Language.   Oberon
  7. :Translator. AmigaOberon V2.00
  8. :History.    V0.1, 03 Dec 1990 Hartmut Goebel
  9. :History.    V1.0, 14 Apr 1991 Hartmut Goebel [hG]
  10. :History.    V1.0b 24 Apr 1991 [hG] -Bugs: doReturn, doRepeat, doIf
  11. :History.    V1.0c 26 Apr 1991 [hG] ^doJoin, _etwas_ optimiert
  12. :History.    V1.1  12 Sep 1991 [hG] + doReformat
  13. :Date.       17 Oct 1991 21:16:35
  14.  
  15. *************************************************************************)
  16.  
  17. MODULE EdMovement;
  18. (* $Debug- *)
  19. IMPORT
  20.   EdGadgets,
  21.   e  : Exec,
  22.   edB: EdBlocks,
  23.   edD: EdDisplay,
  24.   edE: EdErrors,
  25.   edG: EdGlobalVars,
  26.   edL: EdLowLevel,
  27.   g  : Graphics,
  28.   lst: EdLists,
  29.   str: Strings,
  30.   sys: SYSTEM;
  31.  
  32. CONST
  33.   (* Flags für einzelne Kommandos *)
  34.   pageSet* = 0; (* PageSet od. PageUp/Down *)
  35.   pageUp* = 1;  (* PageUp od. PageDown *)
  36.   rfmtParag* = 0;
  37.  
  38.   LineTooLong = "Line too long!";
  39.   LineMarked = "Line marked";
  40.   PingOutOfRange = "ping: out of range";
  41.   PongRangeErrorOrNothingMarked = "pong: range error or nothing marked";
  42.  
  43. VAR
  44.   PagePctg: INTEGER;
  45.  
  46. (*--------------------------------------------------------------------------*)
  47.  
  48. PROCEDURE doToMouse*;
  49. BEGIN
  50.   edD.TextPosition((edG.Mx-edG.XBase) DIV edG.XSize,
  51.                    (edG.My-edG.YBase) DIV edG.YSize);
  52. END doToMouse;
  53.  
  54. (*--------------------------------------------------------------------------*)
  55.  
  56. PROCEDURE^ doReformat*;  (* Forward, wird in doDel und doBS gebraucht *)
  57.  
  58. (*--------------------------------------------------------------------------*)
  59.  
  60. PROCEDURE doUp*;
  61. BEGIN
  62.   IF edG.Text.line # 0 THEN
  63.     edD.PutBackLine;
  64.     DEC(edG.Text.line);
  65.     edG.Text.actLinePtr := edG.Text.actLinePtr.prev(edG.Line);
  66.     edD.TextLoad;
  67.     IF (edG.Text.line < edG.Text.topLine) THEN
  68.       edG.Text.topLinePtr := edG.Text.actLinePtr;
  69.       DEC(edG.Text.topLine);
  70.       IF edG.NoScreenUpdate = 0 THEN
  71.         edD.FastScrollRaster(0,-edG.YSize,edD.Col(0),edD.Row(0),
  72.                        edD.Col(edG.Columns)-1,edD.Row(edG.Rows)-1);
  73.         edD.TextDisplaySeg(0,1);
  74.         EdGadgets.SetPropKnob;
  75.       END;
  76.     END;
  77.   ELSE
  78.     edG.Rc := edE.cmdFailed;
  79.   END;
  80. END doUp;
  81.  
  82.  
  83. PROCEDURE doDown*;
  84. BEGIN
  85.   IF edG.Text.actLinePtr # edG.Text.lineList.tail THEN
  86.     edD.PutBackLine;
  87.     INC(edG.Text.line);
  88.     edG.Text.actLinePtr := edG.Text.actLinePtr.next(edG.Line);
  89.     edD.TextLoad;
  90.     IF (edG.Text.line-edG.Text.topLine >= edG.Rows) THEN
  91.       edG.Text.topLinePtr := edG.Text.topLinePtr.next(edG.Line);
  92.       INC(edG.Text.topLine);
  93.       IF edG.NoScreenUpdate = 0 THEN
  94.         edD.FastScrollRaster(0,edG.YSize,edD.Col(0),edD.Row(0),
  95.                        edD.Col(edG.Columns)-1,edD.Row(edG.Rows)-1);
  96.         edD.TextDisplaySeg(edG.Rows-1,1);
  97.         EdGadgets.SetPropKnob;
  98.       END;
  99.     END;
  100.   ELSE
  101.     edG.Rc := edE.cmdFailed;
  102.   END;
  103. END doDown;
  104.  
  105.  
  106. PROCEDURE doScrollUp*;
  107. BEGIN
  108.   IF edG.Text.topLine > 0 THEN
  109.     IF edG.NoScreenUpdate = 0 THEN
  110.       edD.PutBackLine;
  111.       edD.FastScrollRaster(0,-edG.YSize,edD.Col(0),edD.Row(0),
  112.                      edD.Col(edG.Columns)-1,edD.Row(edG.Rows)-1);
  113.       edG.Text.topLinePtr := edG.Text.topLinePtr.prev(edG.Line);
  114.       edG.Text.actLinePtr := edG.Text.actLinePtr.prev(edG.Line);
  115.       DEC(edG.Text.topLine);
  116.       DEC(edG.Text.line);
  117.       edD.TextLoad;
  118.       edD.TextDisplaySeg(0,1);
  119.       EdGadgets.SetPropKnob;
  120.     END;
  121.   ELSE
  122.     edG.Rc := edE.cmdFailed;
  123.   END;
  124. END doScrollUp;
  125.  
  126.  
  127. PROCEDURE doScrollDown*;
  128. BEGIN
  129.   IF edG.Text.topLine + edG.Rows < edG.Text.numberOfLines THEN
  130.     IF edG.NoScreenUpdate = 0 THEN
  131.       edD.PutBackLine;
  132.       edD.FastScrollRaster(0,edG.YSize,edD.Col(0),edD.Row(0),
  133.                      edD.Col(edG.Columns)-1,edD.Row(edG.Rows)-1);
  134.       edG.Text.topLinePtr := edG.Text.topLinePtr.next(edG.Line);
  135.       edG.Text.actLinePtr := edG.Text.actLinePtr.next(edG.Line);
  136.       INC(edG.Text.topLine);
  137.       INC(edG.Text.line);
  138.       edD.TextLoad;
  139.       edD.TextDisplaySeg(edG.Rows-1,1);
  140.       EdGadgets.SetPropKnob;
  141.     END;
  142.   ELSE
  143.     edG.Rc := edE.cmdFailed;
  144.   END;
  145. END doScrollDown;
  146.  
  147.  
  148. PROCEDURE doDownAdd*;
  149. VAR
  150.   newLine : edG.LinePtr;
  151. BEGIN
  152.   IF edG.Text.line+1 = edG.Text.numberOfLines THEN
  153.     edL.NewLine(newLine,edG.ChunkSize);
  154.     IF newLine # NIL THEN
  155.       lst.AddTail(edG.Text.lineList,newLine);
  156.       INC(edG.Text.numberOfLines);
  157.       INCL(edG.Text.status,edG.modified);
  158.     END;
  159.   END;
  160.   doDown;
  161. END doDownAdd;
  162.  
  163. (*--------------------------------------------------------------------------*)
  164.  
  165. PROCEDURE doTop*;
  166. BEGIN
  167.   edD.PutBackLine;
  168.   edG.Text.line := 0;
  169.   edG.Text.actLinePtr :=edG.Text.lineList.head(edG.Line);
  170.   edD.TextLoad;
  171.   edD.TextSync;
  172.   EdGadgets.SetPropKnob;
  173. END doTop;
  174.  
  175.  
  176. PROCEDURE doBottom*;
  177. BEGIN
  178.   edD.PutBackLine;
  179.   edG.Text.line := edG.Text.numberOfLines-1;
  180.   edG.Text.actLinePtr :=edG.Text.lineList.tail(edG.Line);
  181.   (*edG.Text.topLine := edG.Text.line-edG.Rows;
  182.   IF edG.Text.topLine < 0 THEN
  183.     edG.Text.topLine := 0; END;*)
  184.   edD.TextLoad;
  185.   edD.TextSync;
  186.   EdGadgets.SetPropKnob;
  187. END doBottom;
  188.  
  189.  
  190. PROCEDURE doScreenTop*;
  191. BEGIN
  192.   edD.PutBackLine;
  193.   edG.Text.line := edG.Text.topLine;
  194.   edG.Text.actLinePtr := edG.Text.topLinePtr;
  195.   edD.TextLoad;
  196.   edD.TextSync;
  197. END doScreenTop;
  198.  
  199.  
  200. PROCEDURE doScreenBottom*;
  201. BEGIN
  202.   edD.PutBackLine;
  203.   edG.Text.line := edG.Text.topLine + edG.Rows - 1;
  204.   IF edG.Text.line >= edG.Text.numberOfLines THEN
  205.     edG.Text.line := edG.Text.numberOfLines - 1; END;
  206.   edG.Text.actLinePtr := edG.Text.topLinePtr;
  207.   lst.GoForwardNil(edG.Text.actLinePtr,edG.Text.line-edG.Text.topLine);
  208.   edD.TextLoad;
  209.   edD.TextSync;
  210. END doScreenBottom;
  211.  
  212. (*--------------------------------------------------------------------------*)
  213.  
  214. PROCEDURE doLeft*;
  215. BEGIN
  216.   IF edG.Text.pos #0 THEN
  217.     DEC(edG.Text.pos);
  218.     IF edG.Text.pos < edG.Text.topPos THEN
  219.       edD.TextSync; END;
  220.   ELSE
  221.     edG.Rc := edE.cmdFailed;
  222.   END;
  223. END doLeft;
  224.  
  225.  
  226. PROCEDURE doRight*;
  227. BEGIN
  228.   IF edG.Text.pos < edG.MaxLineLength-2 THEN
  229.     IF edG.Text.pos = edG.LineBufferLen THEN
  230.       edG.LineBuffer[edG.LineBufferLen] := 20X;
  231.       INC(edG.LineBufferLen);
  232.       edG.LineBuffer[edG.LineBufferLen] := 0X;
  233.     END;
  234.     INC(edG.Text.pos);
  235.     IF (edG.Text.pos-edG.Text.topPos >= edG.Columns) THEN
  236.       edD.TextSync; END;
  237.   ELSE
  238.     edG.Rc := edE.cmdFailed;
  239.   END;
  240. END doRight;
  241.  
  242.  
  243. PROCEDURE doWordLeft*;
  244. VAR
  245.   i: INTEGER;
  246. BEGIN
  247.   LOOP
  248.     i := edG.Text.pos;
  249.     IF i # 0 THEN
  250.       REPEAT
  251.         DEC(i);
  252.       UNTIL (i=0) OR (edL.IsAscii(edG.LineBuffer[i]));
  253.     END;
  254.     IF (edG.LineBufferLen=0) OR (edG.Text.pos=0) THEN
  255.       IF (edG.commLineMode IN edG.Status) OR (edG.Text.line = 0) THEN
  256.         EXIT;
  257.       END;
  258.       edD.PutBackLine;
  259.       edG.Text.actLinePtr := edG.Text.actLinePtr.prev(edG.Line);
  260.       DEC(edG.Text.line);
  261.       edG.Text.pos := 0; (* damit's schneller geht *)
  262.       edD.TextLoad;
  263.       edG.Text.pos := edG.LineBufferLen;
  264.     ELSE
  265.       WHILE (i#0) AND (edL.IsAscii(edG.LineBuffer[i])) DO
  266.         DEC(i); END;
  267.       IF (i#0) AND NOT (edL.IsAscii(edG.LineBuffer[i])) THEN
  268.         INC(i); END;
  269.       EXIT;
  270.     END;
  271.   END;
  272.   edG.Text.pos := i;
  273.   edD.TextSync;
  274. END doWordLeft;
  275.  
  276.  
  277. PROCEDURE doWordRight*;
  278. VAR
  279.   i: INTEGER;
  280. BEGIN
  281.   LOOP
  282.     i := edG.Text.pos;
  283.     IF i # edG.LineBufferLen THEN
  284.       WHILE (i<edG.LineBufferLen) AND (edL.IsAscii(edG.LineBuffer[i])) DO
  285.         INC(i); (* zum Wordende *)
  286.       END;
  287.       WHILE (i<edG.LineBufferLen) AND NOT (edL.IsAscii(edG.LineBuffer[i])) DO
  288.         INC(i); (* zum nächsten Wort *)
  289.       END;
  290.       EXIT;
  291.     ELSE
  292.       IF (edG.commLineMode IN edG.Status)
  293.       OR (edG.Text.line = edG.Text.numberOfLines -1) THEN
  294.         i := edG.Text.pos;
  295.         EXIT;
  296.       END;
  297.       edD.PutBackLine;
  298.       edG.Text.actLinePtr := edG.Text.actLinePtr.next(edG.Line);
  299.       INC(edG.Text.line);
  300.       edG.Text.pos := 0; (* wg. Auffüllen mit Spaces *)
  301.       edD.TextLoad;
  302.       IF edL.IsAscii(edG.LineBuffer[0]) THEN
  303.         i := 0;
  304.         EXIT;
  305.       END;
  306.       edG.Text.pos := 0;
  307.     END;
  308.   END;
  309.   edG.Text.pos := i;
  310.   edD.TextSync;
  311. END doWordRight;
  312.  
  313. (*--------------------------------------------------------------------------*)
  314.  
  315. PROCEDURE doFirstColumn*;
  316. BEGIN
  317.   edL.StripEndSpaces;
  318.   IF edG.Text.pos # 0 THEN edG.Text.pos := 0; edD.TextSync; END;
  319. END doFirstColumn;
  320.  
  321.  
  322. PROCEDURE doFirstNb*;
  323. VAR
  324.   i: INTEGER;
  325. BEGIN
  326.   edL.StripEndSpaces;
  327.   i := 0;
  328.   WHILE edG.LineBuffer[i] = 20X DO INC(i); END;
  329.   IF edG.LineBuffer[i] = 0X THEN i := 0; END;
  330.   edG.Text.pos := i;
  331.   edD.TextSync;
  332. END doFirstNb;
  333.  
  334.  
  335. PROCEDURE doLastColumn*;
  336. VAR
  337.   i: INTEGER;
  338. BEGIN
  339.   edL.StripEndSpaces;
  340.   edG.Text.pos := edG.LineBufferLen;
  341.   edD.TextSync;
  342. END doLastColumn;
  343.  
  344. (*--------------------------------------------------------------------------*)
  345.  
  346. PROCEDURE doTab*;
  347. VAR
  348.   n: INTEGER;
  349. BEGIN
  350.   n := SHORT(edG.Text.tabStop-(edG.Text.pos MOD edG.Text.tabStop));
  351.   REPEAT
  352.     doRight;
  353.     DEC(n);
  354.   UNTIL n = 0;
  355. END doTab;
  356.  
  357.  
  358. PROCEDURE doBackTab*;
  359. VAR
  360.   n: INTEGER;
  361. BEGIN
  362.   n := SHORT(edG.Text.pos MOD edG.Text.tabStop);
  363.   IF n = 0 THEN  (* genau auf Tabposition *)
  364.     n := SHORT(edG.Text.tabStop); END;
  365.   REPEAT
  366.     doLeft;
  367.     DEC(n);
  368.   UNTIL n = 0;
  369. END doBackTab;
  370.  
  371. (*--------------------------------------------------------------------------*)
  372.  
  373. PROCEDURE doDel*;
  374. VAR
  375.   buf : edG.StringPtr;
  376. BEGIN
  377.   IF edG.LineBuffer[edG.Text.pos] # 0X THEN
  378.     str.Delete(edG.LineBuffer,edG.Text.pos,1);
  379.     DEC(edG.LineBufferLen);
  380.     edD.FastScrollRaster(edG.XSize,0,
  381.            edD.Col(edG.Text.pos-edG.Text.topPos),
  382.            edD.Row(SHORT(edG.Text.line-edG.Text.topLine)),
  383.            edD.Col(edG.Columns)-1,
  384.            edD.Row(SHORT(edG.Text.line-edG.Text.topLine+1))-1);
  385.     IF (edG.LineBufferLen >= edG.Text.topPos+edG.Columns) THEN
  386.       edD.SetPen(edG.Text.line);
  387.       g.Move(edG.RPort,edD.ColT(edG.Columns-1),
  388.             edD.RowT(SHORT(edG.Text.line-edG.Text.topLine)));
  389.       buf := sys.ADR(edG.LineBuffer);
  390.       INC(buf,edG.Text.topPos+edG.Columns-1);
  391.       g.Text(edG.RPort,buf^,1);
  392.     END;
  393.     IF NOT (edG.commLineMode IN edG.Status)
  394.     AND (edG.wordWrap IN edG.Text.status) THEN
  395.       edG.ArgSet := {};
  396.       doReformat;
  397.     END;
  398.   ELSE
  399.     edG.Rc := edE.cmdFailed;
  400.   END;
  401. END doDel;
  402.  
  403.  
  404. PROCEDURE doBs*;
  405. VAR
  406.   buf : edG.StringPtr;
  407. BEGIN
  408.   IF edG.Text.pos # 0 THEN
  409.     str.Delete(edG.LineBuffer,edG.Text.pos-1,1);
  410.     DEC(edG.Text.pos);
  411.     DEC(edG.LineBufferLen);
  412.     IF edG.Text.pos < edG.Text.topPos THEN
  413.       edD.TextSync;
  414.     ELSE
  415.       edD.FastScrollRaster(edG.XSize, 0,
  416.            edD.Col(edG.Text.pos-edG.Text.topPos),
  417.            edD.Row(SHORT(edG.Text.line-edG.Text.topLine)),edD.Col(edG.Columns)-1,
  418.            edD.Row(SHORT(edG.Text.line-edG.Text.topLine+1))-1);
  419.       IF (edG.LineBufferLen >= edG.Text.topPos+edG.Columns) THEN
  420.         edD.SetPen(edG.Text.line);
  421.         g.Move(edG.RPort,edD.ColT(edG.Columns-1),
  422.                edD.RowT(SHORT(edG.Text.line-edG.Text.topLine)));
  423.         buf := sys.ADR(edG.LineBuffer);
  424.         INC(buf,edG.Text.topPos+edG.Columns);
  425.         g.Text(edG.RPort,buf^,1);
  426.       END;
  427.     END;
  428.     IF NOT (edG.commLineMode IN edG.Status)
  429.     AND (edG.wordWrap IN edG.Text.status) THEN
  430.       edG.ArgSet := {};
  431.       doReformat;
  432.     END;
  433.   ELSE
  434.     edG.Rc := edE.cmdFailed;
  435.   END;
  436. END doBs;
  437.  
  438.  
  439. PROCEDURE doRemEOL*;
  440. BEGIN
  441.   edG.LineBufferLen := edG.Text.pos;
  442.   edG.LineBuffer[edG.LineBufferLen] := 0X;
  443.   edD.TextRedisplayCurrentLine;
  444. END doRemEOL;
  445.  
  446. (*----------------------------------------------------------------------*)
  447.  
  448. PROCEDURE InsertLine(newLine: edG.LinePtr; Behind: BOOLEAN);
  449. BEGIN
  450.   edD.PutBackLine;
  451.   IF Behind THEN
  452.     lst.AddBehind(edG.Text.lineList,newLine,edG.Text.actLinePtr);
  453.     edB.HoldBlockLines(FALSE);
  454.   ELSE
  455.     lst.AddBefore(edG.Text.lineList,newLine,edG.Text.actLinePtr);
  456.     IF edG.Text.topLinePtr = edG.Text.actLinePtr THEN
  457.       edG.Text.topLinePtr := newLine; END;
  458.     edG.Text.actLinePtr := newLine;
  459.     edD.TextLoad;
  460.     DEC(edG.Text.line);
  461.     edB.HoldBlockLines(FALSE);
  462.     INC(edG.Text.line);
  463.   END;
  464.   INC(edG.Text.numberOfLines);
  465.   INCL(edG.Text.status,edG.modified);
  466.   IF edG.NoScreenUpdate = 0 THEN
  467.     g.ScrollRaster(edG.RPort,0,-edG.YSize,edD.Col(0),
  468.                    edD.Row(SHORT(edG.Text.line-edG.Text.topLine)),
  469.                    edD.Col(edG.Columns)-1,edD.Row(edG.Rows)-1);
  470.     edD.TextDisplaySeg(SHORT(edG.Text.line-edG.Text.topLine),2);
  471.   END;
  472. END InsertLine;
  473.  
  474.  
  475. PROCEDURE doInsLine*;
  476. VAR
  477.   newLine: edG.LinePtr;
  478. BEGIN
  479.   edL.NewLine(newLine,edG.ChunkSize);
  480.   IF edG.memoryFail IN edG.Status THEN
  481.     edG.Rc := edE.cmdSevere;
  482.     RETURN;
  483.   END;
  484.   InsertLine(newLine,FALSE);
  485. END doInsLine;
  486.  
  487.  
  488. PROCEDURE doUndelLine*;
  489. VAR
  490.   newLine: edG.LinePtr;
  491. BEGIN
  492.   IF edG.DelLinePtr = NIL THEN edG.Rc := edE.cmdFailed; RETURN END;
  493.   newLine := edL.CreateLineCopy(edG.DelLinePtr);
  494.   IF newLine=NIL THEN edG.Rc := edE.cmdSevere; RETURN END;
  495.   InsertLine(newLine,FALSE);
  496. END doUndelLine;
  497.  
  498.  
  499. PROCEDURE doDelLine*;
  500. VAR
  501.   This: edG.LinePtr;
  502. BEGIN
  503.   IF edG.Text.numberOfLines > 1 THEN
  504.     INCL(edG.Text.status,edG.modified);
  505.     edD.PutBackLine;
  506.     This := edG.Text.actLinePtr;
  507.     edB.HoldBlockLines(TRUE);
  508.     edG.Text.actLinePtr := edG.Text.actLinePtr.next(edG.Line);
  509.     lst.Remove(edG.Text.lineList,This);
  510.     IF edG.LineBufferLen > 0 THEN (* nur retten, wenn was drin steht *)
  511.       IF edG.DelLinePtr # NIL THEN
  512.         e.FreeMem(edG.DelLinePtr(edG.Line).string,edG.DelLinePtr(edG.Line).len);
  513.         e.FreeMem(edG.DelLinePtr,edG.LineAllocSize);
  514.       END;
  515.       edG.DelLinePtr := This;
  516.     ELSE
  517.       e.FreeMem(This(edG.Line).string,This(edG.Line).len);
  518.       e.FreeMem(This,edG.LineAllocSize);
  519.     END;
  520.     DEC(edG.Text.numberOfLines);
  521.     IF edG.Text.actLinePtr = NIL THEN (* es war die letzte Ziele *)
  522.       edG.Text.actLinePtr := edG.Text.lineList.tail(edG.Line);
  523.       DEC(edG.Text.line);    (* eine Zeile vor *)
  524.     END;
  525.     edD.TextLoad;
  526.     IF edG.Text.line < edG.Text.topLine THEN
  527.       edD.TextSync;
  528.       RETURN;
  529.     ELSIF edG.Text.line = edG.Text.topLine THEN
  530.       edG.Text.topLinePtr := edG.Text.actLinePtr;
  531.     END;
  532.     IF edG.NoScreenUpdate = 0 THEN
  533.       g.ScrollRaster(edG.RPort,0,edG.YSize,edD.Col(0),
  534.                      edD.Row(SHORT(edG.Text.line-edG.Text.topLine+1)),
  535.                      edD.Col(edG.Columns)-1,edD.Row(edG.Rows)-1);
  536.       edD.TextRedisplayCurrentLine;
  537.       edD.TextDisplaySeg(edG.Rows-1,1);
  538.     END;
  539.   ELSE
  540.     edG.Text.pos := 0;
  541.     doRemEOL;
  542.     EXCL(edG.Text.status,edG.modified);
  543.   END;
  544. END doDelLine;
  545.  
  546.  
  547. PROCEDURE doJoin*;
  548. VAR
  549.   i: INTEGER;
  550.   next: edG.LinePtr;
  551. BEGIN
  552.   edL.StripEndSpaces;
  553.   i := edG.LineBufferLen;
  554.   IF (edG.Text.line+1 < edG.Text.numberOfLines)
  555.   AND (i+str.Length(next(edG.Line).string^)<edG.MaxLineLength)
  556.   THEN
  557.     next := edG.Text.actLinePtr.next(edG.Line);
  558.     IF (i # 0) AND (edG.LineBuffer[i] # 20X) THEN
  559.       edG.LineBuffer[i] := " "; edG.LineBuffer[i+1] := "\o";
  560.     END;
  561.     i := 0;
  562.     WHILE next(edG.Line).string[i] = 20X DO
  563.       INC(i); END;
  564.     IF i > 0 THEN str.Delete(next(edG.Line).string^,0,i); END;
  565.     str.Append(edG.LineBuffer,next(edG.Line).string^);
  566.     edG.LineBufferLen := str.Length(edG.LineBuffer);
  567.     edD.PutBackLine;
  568.     INC(edG.Text.line);
  569.     edB.HoldBlockLines(TRUE);
  570.     DEC(edG.Text.line);
  571.     edL.FreeLines(edG.Text.lineList,next,next);
  572.     DEC(edG.Text.numberOfLines);
  573.     edD.TextLoad;
  574.     IF edG.NoScreenUpdate = 0 THEN
  575.       g.ScrollRaster(edG.RPort,0,edG.YSize,edD.Col(0),
  576.                      edD.Row(SHORT(edG.Text.line-edG.Text.topLine+1)),
  577.                      edD.Col(edG.Columns)-1,edD.Row(edG.Rows)-1);
  578.       edD.TextRedisplayCurrentLine;
  579.       edD.TextDisplaySeg(edG.Rows-1,1);
  580.     END;
  581.   ELSE
  582.     edG.Rc := edE.cmdFailed;
  583.   END;
  584. END doJoin;
  585.  
  586.  
  587. PROCEDURE doSplit*;
  588. VAR
  589.   len : INTEGER;
  590.   newLine : edG.LinePtr;
  591. BEGIN
  592.   len := edG.LineBufferLen-edG.Text.pos;
  593.   edL.NewLine(newLine,len+edG.ChunkSize-(len MOD edG.ChunkSize));
  594.   IF edG.memoryFail IN edG.Status THEN
  595.     edG.Rc := edE.cmdSevere;
  596.     RETURN;
  597.   END;
  598.   str.Cut(edG.LineBuffer,edG.Text.pos,len,newLine(edG.Line).string^);
  599.   edG.LineBuffer[edG.Text.pos] := 0X;
  600.   len := SHORT(edG.Text.line-edG.Text.topLine);
  601.   g.SetAPen(edG.RPort,0);
  602.   g.RectFill(edG.RPort,edD.Col(0),edD.Row(len),
  603.              edG.XBase+edG.XPixs,edD.Row(len+1)-1);
  604.   InsertLine(newLine,TRUE);
  605.   doDown;
  606.   doUp;
  607. END doSplit;
  608.  
  609. (*----------------------------------------------------------------------*)
  610.  
  611. (*
  612.  * GOTO [+/-]N
  613.  * GOTO BLOCK   start of block
  614.  * GOTO START   start of block
  615.  * GOTO END     end of block
  616.  *)
  617.  
  618. PROCEDURE JumpToLine*(n: LONGINT);
  619. BEGIN
  620.   IF n >= edG.Text.numberOfLines THEN
  621.     n := edG.Text.numberOfLines - 1; END;
  622.   IF (n >= 0) AND (n # edG.Text.line) THEN
  623.     edD.PutBackLine;
  624.     IF n = 0 THEN
  625.       edG.Text.actLinePtr :=edG.Text.lineList.head(edG.Line);
  626.     ELSIF n = edG.Text.numberOfLines-1 THEN
  627.       edG.Text.actLinePtr :=edG.Text.lineList.tail(edG.Line);
  628.     ELSIF n < edG.Text.line THEN
  629.       lst.GoBackwardNil(edG.Text.actLinePtr,edG.Text.line-n);
  630.     ELSE
  631.       lst.GoForwardNil(edG.Text.actLinePtr,n-edG.Text.line);
  632.     END;
  633.     edG.Text.line := n;
  634.     edD.TextLoad;
  635.     edD.TextSync;
  636.     EdGadgets.SetPropKnob;
  637.   END;
  638. END JumpToLine;
  639.  
  640.  
  641. PROCEDURE doGoto*;
  642. VAR
  643.   n : LONGINT;
  644.   ok : BOOLEAN;
  645. BEGIN
  646.   CASE CAP(edG.Arg[0][0]) OF
  647.   |"B","S": IF edG.Text = edG.Block.Owner THEN
  648.               edG.Text.line := edG.Block.SNum;
  649.               edG.Text.actLinePtr := edG.Block.mark.head;
  650.             ELSE
  651.               edG.Text.line := 0;
  652.               edG.Text.actLinePtr := edG.Text.lineList.head;
  653.             END;
  654.   |"E": IF edG.Text = edG.Block.Owner THEN
  655.               edG.Text.line := edG.Block.ENum;
  656.               edG.Text.actLinePtr := edG.Block.mark.tail;
  657.             ELSE
  658.               edG.Text.line := edG.Text.numberOfLines-1;
  659.               edG.Text.actLinePtr := edG.Text.lineList.tail;
  660.             END;
  661.   |ELSE IF NOT edL.StrToInt(edG.Arg[0],n) THEN
  662.           edG.Rc := edE.cmdError;
  663.           edL.Title(edG.BadArgument);
  664.           RETURN;
  665.         END;
  666.         IF edG.Arg[0][0] < "0" THEN (* mit Vorzeichen => relativ *)
  667.           n := n+edG.Text.line;
  668.         ELSE
  669.           DEC(n); (* intern bei Null anfangen *)
  670.         END;
  671.         JumpToLine(n);
  672.         RETURN;
  673.   END;
  674.   edD.TextSync;
  675. END doGoto;
  676.  
  677. (*----------------------------------------------------------------------*)
  678.  
  679. (*
  680.  *  PAGEUP
  681.  *  PAGEDOWN
  682.  *  PAGESET n   (n = 0 to 100 for percentage of #rows to scroll, minimum 1)
  683.  *              can be > 100.
  684.  *)
  685.  
  686. PROCEDURE doPage*;
  687. VAR
  688.   n: INTEGER;
  689.   long: LONGINT;
  690. BEGIN
  691.   IF pageSet IN edG.ArgSet THEN
  692.     IF edL.StrToInt(edG.Arg[0],long) THEN
  693.       PagePctg := ABS(SHORT(long));
  694.     ELSE
  695.       edL.Title(edG.BadArgument); edG.Rc := edE.cmdFailed;
  696.     END;
  697.     RETURN;
  698.   END;
  699.   n := edG.Rows * PagePctg DIV 100; IF n = 0 THEN n := 1; END;
  700.   IF pageUp IN edG.ArgSet THEN n := -n; END;
  701.   IF (n > 0) AND (edG.Text.topLine >= edG.Text.numberOfLines - edG.Rows) THEN
  702.       RETURN; END;
  703.   edD.PutBackLine;
  704.   INC(edG.Text.line,n);     (* alle Werte per Hand setzen, da TextSync    *)
  705.   INC(edG.Text.topLine,n);  (* sonst nur einen halben Bildschirm scrollt! *)
  706.   IF edG.Text.line >= edG.Text.numberOfLines THEN
  707.     edG.Text.line := edG.Text.numberOfLines - 1;
  708.   ELSIF edG.Text.line < 0 THEN
  709.     edG.Text.line := 0;
  710.   END;
  711.   IF edG.Text.topLine >= edG.Text.numberOfLines THEN
  712.     edG.Text.topLine := edG.Text.numberOfLines - edG.Rows - 1;
  713.   ELSIF edG.Text.topLine < 0 THEN
  714.     edG.Text.topLine := 0;
  715.   END;
  716.   IF n < 0 THEN
  717.     lst.GoBackwardNil(edG.Text.actLinePtr,-n);
  718.     IF edG.Text.actLinePtr = NIL THEN
  719.       edG.Text.actLinePtr := edG.Text.lineList.head(edG.Line); END;
  720.     edG.Text.topLinePtr := edG.Text.actLinePtr;
  721.     lst.GoBackwardNil(edG.Text.topLinePtr,edG.Text.line-edG.Text.topLine);
  722.   ELSE
  723.     lst.GoForwardNil(edG.Text.actLinePtr,n);
  724.     IF edG.Text.actLinePtr = NIL THEN
  725.       edG.Text.actLinePtr := edG.Text.lineList.tail(edG.Line); END;
  726.     edG.Text.topLinePtr := edG.Text.actLinePtr;
  727.     lst.GoBackwardNil(edG.Text.topLinePtr,edG.Text.line-edG.Text.topLine);
  728.   END;
  729.   edD.TextLoad;
  730.   edD.TextSync;
  731.   IF NOT(edG.alreadyRedrawn IN edG.Status) THEN edD.TextRedisplay; END;
  732. END doPage;
  733.  
  734. (*----------------------------------------------------------------------*)
  735.  
  736. PROCEDURE doPing*;
  737. VAR
  738.   long: LONGINT;
  739. BEGIN
  740.   IF edL.StrToInt(edG.Arg[0],long) AND (long<edG.NumPingPongs) THEN
  741.     edG.PingPong[long].txt  := edG.Text;
  742.     edG.PingPong[long].line := edG.Text.line;
  743.     edG.PingPong[long].pos  := edG.Text.pos;
  744.     edG.Rc := edE.cmdValid2; edL.Title(LineMarked);
  745.   ELSE
  746.     edG.Rc := edE.cmdFailed; edL.Title(PingOutOfRange);
  747.   END;
  748. END doPing;
  749.  
  750.  
  751. PROCEDURE doPong*;
  752. VAR
  753.   long: LONGINT;
  754. BEGIN
  755.   IF edL.StrToInt(edG.Arg[0],long) AND (long<edG.NumPingPongs)
  756.   AND (edG.PingPong[long].txt # NIL)
  757.   AND (edG.PingPong[long].line<edG.Text.numberOfLines) THEN
  758.     INC(edG.NoScreenUpdate);
  759.     edD.SwitchEdit(edG.PingPong[long].txt);
  760.     edG.Text.pos := edG.PingPong[long].pos;
  761.     DEC(edG.NoScreenUpdate);
  762.     JumpToLine(edG.PingPong[long].line);
  763.   ELSE
  764.     edG.Rc := edE.cmdFailed; edL.Title(PongRangeErrorOrNothingMarked);
  765.   END;
  766. END doPong;
  767.  
  768.  
  769. PROCEDURE ClearPingPongs;
  770. VAR
  771.   i: INTEGER;
  772. BEGIN
  773.   i := edG.NumPingPongs;
  774.   REPEAT
  775.     DEC(i);
  776.     edG.PingPong[i].txt := NIL;
  777.   UNTIL i = 0;
  778. END ClearPingPongs;
  779.  
  780. (*-------------------------------------------------------------------------*)
  781.  
  782. (* schreibt <text> in den Buffer und auf den Scrren, beachtet InsertMode *)
  783.  
  784. PROCEDURE TextWrite*(text: edG.StringPtr);
  785. VAR
  786.   len,i : INTEGER;
  787.   buf : edG.StringPtr;
  788. BEGIN
  789.   len := str.Length(text^);
  790.   IF edG.LineBufferLen+len >= edG.MaxLineLength-1 THEN
  791.     edD.TextLoad;
  792.     edD.TextSync;
  793.   END;
  794.   IF NOT (edG.insertMode IN edG.Text.status) THEN
  795.     IF (edG.Text.pos+len >= edG.MaxLineLength-1) THEN
  796.       edL.Title(LineTooLong); edG.Rc := edE.cmdFailed;
  797.       RETURN;
  798.     END;
  799.     buf := sys.ADR(edG.LineBuffer[edG.Text.pos]);
  800.     e.CopyMem(text^,buf^,len);
  801.     IF (edG.Text.pos+len > edG.LineBufferLen) THEN
  802.       edG.LineBufferLen := edG.Text.pos+len;
  803.       edG.LineBuffer[edG.LineBufferLen] := 0X;
  804.     END;
  805.   ELSE
  806.     IF (edG.LineBufferLen+len >= edG.MaxLineLength-1) THEN
  807.       edL.Title(LineTooLong); edG.Rc := edE.cmdFailed;
  808.       RETURN;
  809.     END;
  810.     str.Insert(edG.LineBuffer,edG.Text.pos,text^);
  811.     INC(edG.LineBufferLen,len);
  812.     IF (len < edG.Columns - (edG.Text.pos-edG.Text.topPos)) THEN
  813.       edD.FastScrollRaster(-len*edG.XSize,0,
  814.          edD.Col(edG.Text.pos-edG.Text.topPos),
  815.          edD.Row(SHORT(edG.Text.line-edG.Text.topLine)),edD.Col(edG.Columns),
  816.          edD.Row(SHORT(edG.Text.line-edG.Text.topLine+1))-1);
  817.     END;
  818.   END; (* IF NOT InsertMode *)
  819.   IF (edG.Text.pos-edG.Text.topPos+len > edG.Columns) THEN
  820.     i := edG.Columns-edG.Text.pos+edG.Text.topPos;
  821.   ELSE
  822.     i := len;
  823.   END;
  824.   edD.SetPen(edG.Text.line);
  825.   g.Move(edG.RPort,edD.ColT(edG.Text.pos-edG.Text.topPos),
  826.          edD.RowT(SHORT(edG.Text.line-edG.Text.topLine)));
  827.   g.Text(edG.RPort,text^,i);
  828.   INC(edG.Text.pos,len);
  829.   IF (edG.Text.pos-edG.Text.topPos >= edG.Columns) THEN
  830.     edD.TextSync; END;
  831.   IF NOT (edG.commLineMode IN edG.Status) AND (edG.NoScreenUpdate = 0)
  832.   AND (edG.wordWrap IN edG.Text.status) THEN
  833.     doReformat; END;
  834. END TextWrite;
  835.  
  836. (*-------------------------------------------------------------------------*)
  837. (*
  838.  *  rfmtParag  : force reformat entire paragraph
  839.  * ~rfmtParag  : only until line equalizes (from TextWrite())
  840.  *
  841.  * What is a paragraph?   A paragraph ends whenever the left justification
  842.  * gets larger, or on a blank line.
  843.  *)
  844. (* $Debug= *)
  845. PROCEDURE doReformat*;
  846. VAR
  847.   string: edG.StringPtr;
  848.   lnsc, fnst, fnsc: INTEGER;
  849.   column: INTEGER;
  850.   srow, crow, erow: LONGINT;
  851.   cptr: edG.LinePtr;     (* origin line *)
  852.   dins: INTEGER;         (* relative insert lines/delete lines   *)
  853.   moded: BOOLEAN;        (* any modifications done at all?       *)
  854.   checked: BOOLEAN;      (* for cursor positioning.              *)
  855.   nlok: BOOLEAN;
  856.   i, indent: INTEGER;
  857. BEGIN
  858.   column := edG.Text.pos;
  859.   srow := edG.Text.line; erow := srow; crow := srow;
  860.   cptr  := edG.Text.actLinePtr;
  861.   dins := 0; moded := FALSE; checked := FALSE;
  862.   IF (edG.Text.margin = 0) THEN edG.Text.margin := 75; END;
  863.   INC(edG.NoScreenUpdate);
  864.  
  865.   LOOP
  866.     string := edG.Text.actLinePtr.next(edG.Line).string;
  867.     fnsc := edL.FirstNoSpace(sys.ADR(edG.LineBuffer));
  868.     fnst := edL.FirstNoSpace(string);
  869.     nlok := (edG.Text.line + 1 < edG.Text.numberOfLines) AND (fnsc >= fnst);
  870.     IF string[0] = 0X THEN
  871.       nlok := FALSE; END;
  872.     lnsc := edL.LastNoSpace(sys.ADR(edG.LineBuffer));
  873.     IF (lnsc < edG.Text.margin) THEN
  874.       (* space at end of line for margin-lnsc-2 letter word *)
  875.       IF NOT nlok THEN      (* but no more data to joinup *)
  876.         EXIT; END;          (* done *)
  877.       IF (edG.Text.margin-lnsc-2 >= edL.WordLen(sys.ADR(string[fnst]))) THEN
  878.         edG.Text.pos := 0;
  879.         edG.LineBufferLen := edL.LastNoSpace(sys.ADR(edG.LineBuffer));
  880.         IF (edG.LineBuffer[edG.LineBufferLen] # 0X) THEN
  881.           INC(edG.LineBufferLen); END;
  882.         moded := TRUE;
  883.         DEC(dins);
  884.         doJoin;
  885.         IF edG.Rc >= edE.cmdFailed THEN
  886.           INC(dins);
  887.           edL.Title(edG.ErrorMarginOver124);
  888.           EXIT;          (* stop reformating *)
  889.         END;
  890.       ELSE
  891.         IF NOT (rfmtParag IN edG.ArgSet) THEN   (* if couldn't mod line, and *)
  892.           EXIT; END;                     (* TextWrite, don't update any more *)
  893.         doDown;
  894.         erow := edG.Text.line;
  895.       END;
  896.     ELSE                    (* no space, need to split      *)
  897.       LOOP                  (* find start of prev word      *)
  898.         WHILE (lnsc # 0) & (edG.LineBuffer[lnsc] # ' ') DO
  899.           DEC(lnsc); END;
  900.         IF (lnsc < edG.Text.margin) THEN
  901.           EXIT; END;
  902.         DEC(lnsc);          (* edG.Text.margin >= 1 !! *)
  903.       END;
  904.       IF (lnsc # 0) THEN             (* ok to split at word          *)
  905.         INC(lnsc);
  906.         INC(dins);
  907.         edG.Text.pos := lnsc;
  908.         doSplit;               (* Split at point LNSC          *)
  909.         edG.Text.pos := 0;     (* avoid FillUpSpaces *)
  910.         doDown;                (* must insert proper amount?   *)
  911.         IF nlok THEN
  912.           indent :=  fnst;
  913.         ELSE
  914.           indent := fnsc;
  915.         END;
  916.         IF NOT checked THEN
  917.           checked := TRUE;
  918.           IF (lnsc <= column) THEN   (* if split before cursor   *)
  919.             column := column - edG.Text.pos + indent;
  920.             cptr := cptr.next(edG.Line); INC(crow);
  921.           END;
  922.         END;
  923.         IF (indent # 0) AND (edG.LineBufferLen + indent < 253) THEN
  924.           i := str.Length(edG.LineBuffer)+1;
  925.           REPEAT
  926.             edG.LineBuffer[indent+i] := edG.LineBuffer[i];
  927.             DEC(i);
  928.           UNTIL i < 0;
  929.           INC(edG.LineBufferLen,indent);
  930.           REPEAT
  931.             DEC(indent);
  932.             edG.LineBuffer[indent] := " ";
  933.           UNTIL indent = 0;
  934.         END;
  935.         erow := edG.Text.line;
  936.       ELSE
  937.         IF NOT (rfmtParag IN edG.ArgSet) THEN EXIT; END;
  938.         doDown;
  939.       END;
  940.     END;
  941.   END; (* LOOP *)
  942.  
  943.   IF (column < 0) OR (column > 200) THEN
  944.     column := 0; END;
  945.   edD.PutBackLine;
  946.   edG.Text.actLinePtr := cptr;
  947.   edG.Text.line := crow;
  948.   edG.Text.pos := column;
  949.   DEC(edG.NoScreenUpdate);
  950.   edD.TextLoad;
  951.   edD.TextSync;
  952.   IF (dins # 0) OR (srow >= edG.Text.numberOfLines)
  953.   OR (srow < edG.Text.topLine) OR (srow >= edG.Text.topLine + edG.Rows) THEN
  954.     IF (srow >= edG.Text.numberOfLines) THEN
  955.       srow := edG.Text.numberOfLines - 1;
  956.     END;
  957.     IF NOT (edG.alreadyRedrawn IN edG.Status) THEN
  958.       edD.TextRedisplay; END;
  959.   ELSE
  960.     IF (erow = srow) AND moded THEN
  961.       edD.TextRedisplayCurrentLine;
  962.     ELSIF NOT (edG.alreadyRedrawn IN edG.Status) THEN
  963.       INC(erow);
  964.       IF (erow - edG.Text.topLine > edG.Rows) THEN
  965.         erow := edG.Text.topLine + edG.Rows; END;
  966.       g.SetAPen(edG.RPort, 0);
  967.       g.RectFill(edG.RPort, edD.Col(0), edD.Row(SHORT(srow - edG.Text.topLine)),
  968.                  edG.XBase+edG.XPixs, edD.Row(SHORT(erow - edG.Text.topLine))-1);
  969.       g.SetAPen(edG.RPort, 1);
  970.       edD.TextDisplaySeg(SHORT(srow-edG.Text.topLine),SHORT(erow-srow));
  971.     END;
  972.   END;
  973.   edG.Text.pos := column;
  974.   edL.FillUpSpaces;
  975. END doReformat;
  976. (* $Debug-*)
  977. (*-----------------------------------------------------------------------*)
  978.  
  979. BEGIN
  980.   PagePctg := 80;
  981.   ClearPingPongs;
  982. END EdMovement.
  983.